package concurrency.exclusion_mutuelle.v_synchronized;

import java.util.concurrent.Semaphore;

public class ExclusionMutuelleSemaphore {
	
	private int repetition;
	
	// === VARIABLES PARTAGEES ===
	private int varPartagee;
	private Semaphore mutex;
	// ===========================
	
	public ExclusionMutuelleSemaphore(int repetition) {		
		this.repetition = repetition;
		// === INITIALISATION ===
		varPartagee = 0;
		mutex = new Semaphore(1);
		// ======================
	}
	
	public void incrementer() throws InterruptedException {
		mutex.acquire(); // P(mutex)
		// Debut SC
		varPartagee++;
		information();
		// Fin SC
		mutex.release(); // V(mutex)
	}
	
	public void decrementer() throws InterruptedException {
		mutex.acquire(); // P(mutex)
		// Debut SC
		varPartagee--;
		information(); 
		// Fin SC
		mutex.release(); // V(mutex)
	}
	
	private void information() {
		String des = Thread.currentThread().getName() + " VAR : " + varPartagee;
		System.out.println(des);
	}
	
	private class Processus extends Thread {
		private final boolean typeProcess;
		
		private Processus(final String name, final boolean typeProcess) {
			setName(name);
			this.typeProcess = typeProcess;
		}
		
		@Override
		public void run() {
			try {
			for (int i = 0; i < repetition; i++) {
				if (typeProcess) {
					incrementer();
				} else {
					decrementer();
				}
			}
			} catch (InterruptedException ie) {
				ie.printStackTrace();
			}
		}
	}
	
	public static void main(String[] args) {
		ExclusionMutuelleSemaphore ex = new ExclusionMutuelleSemaphore(200);
		Processus pInc = ex.new Processus("Incremente", true);
		Processus pDec = ex.new Processus("Decremente", false);
		pInc.start();
		pDec.start();
	}
}
